package net.ib.mtalk.network.task;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import android.content.ContentProviderOperation;
import android.content.Context;
import android.content.OperationApplicationException;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.os.RemoteException;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import net.ib.mntalk.protocol.Common;
import net.ib.mntalk.protocol.Common.ContactAccountInfo;
import net.ib.mntalk.protocol.Common.ContactInfo;
import net.ib.mntalk.protocol.Common.Name;
import net.ib.mntalk.protocol.Common.UUIDMsg;
import net.ib.mntalk.protocol.Session.AddContactsReq;
import net.ib.mntalk.protocol.Session.AddContactsRes;
import net.ib.mntalk.protocol.Session.GetContactsRes;
import net.ib.mtalk.constant.HandlerMsgConst;
import net.ib.mtalk.constant.MTalkConstant;
import net.ib.mtalk.database.DatabaseContract.ContactTable;
import net.ib.mtalk.database.helper.ContactDatabaseHelper;
import net.ib.mtalk.network.MethodId.Session;
import net.ib.mtalk.network.TcpEnvelope;
import net.ib.mtalk.sync.ContactComparator;
import net.ib.mtalk.sync.ContactComparator.ContactChangeAction;
import net.ib.mtalk.ui.buddy.talk.BuddyTalkListActivity;
import net.ib.mtalk.util.GpbSupport;
import net.ib.mtalk.util.MTalkLogWriter;
import net.ib.mtalk.util.NotifyingAsyncQueryHandler;

public class AddContactsTask extends AsyncNetTask {
	
	private AddContactsReq mAddContactsReq = new AddContactsReq();
	private ArrayList<ContentProviderOperation> applicationcCPO = new ArrayList<ContentProviderOperation>();
	private Map<String, String> map = new HashMap<String, String>();
	private Map<String, Integer> map_version = new HashMap<String, Integer>();
	
	public AddContactsTask(Context _context, Handler _uiHandler) {
		super(_context, _uiHandler);
		mContext = _context;
		mUiHandler = _uiHandler;
	}
	
	/**
	 * 주소록을 Compare 해서 해당 Action 에 대해 알맞은 작업을 해준다.
	 * 	0	:	_id
	 * 	1	:	Number
	 * 	2	:	rawID
	 * 	3	: 	name
	 *  4	:	version
	 */
	ContactChangeAction action = new ContactChangeAction() {
		@Override
		public void onNumberInserted(Cursor contact, Cursor app) {
			/**
			 * Server 로 번호 전송
			 */
			mAddContactsReq.addContact(new ContactInfo().setAccount(new ContactAccountInfo().setAccountValue(contact.getString(contact.getColumnIndexOrThrow(Phone.NUMBER))).setType(Common.Phone))
																.setName(new Name().setFirstName(contact.getString(contact.getColumnIndexOrThrow(Phone.DISPLAY_NAME)))));
			map.put(contact.getString(contact.getColumnIndexOrThrow(Phone.RAW_CONTACT_ID)), contact.getString(contact.getColumnIndexOrThrow(Phone.DISPLAY_NAME)));
			map_version.put(contact.getString(contact.getColumnIndexOrThrow(Phone.RAW_CONTACT_ID)), contact.getInt(contact.getColumnIndexOrThrow(Phone.DATA_VERSION)));
		}
		
		@Override
		public void onNumberDeleted(Cursor contact, Cursor app) {
			/**
			 * N-Screen 을 지원하므로 아무 것도 하지 않는다.
			 * ContactTable data만 지울 뿐
			 */
			applicationcCPO.add(ContactDatabaseHelper.delete(app.getLong(app.getColumnIndexOrThrow(ContactTable.KEY_CONTACT_PHONE_ID))));
		}
		
		@Override
		public void onNumberChanged(Cursor contact, Cursor app) {
			/**
			 * 변경된 번호 Server 로 전송
			 * Buddy 중 해당 번호 or Raw ID 를 가진 Buddy 에 대해서 이름 변경(to PushName) + Raw id 삭제 
			 */
			applicationcCPO.add(ContactDatabaseHelper.updateContact(app.getLong(app.getColumnIndexOrThrow(ContactTable.KEY_CONTACT_PHONE_ID)),
					ContactTable.KEY_CONTACT_NUMBER,
					contact.getString(contact.getColumnIndexOrThrow(Phone.NUMBER)),
					contact.getString(contact.getColumnIndexOrThrow(Phone.DATA_VERSION))));
			
			mAddContactsReq.addContact(new ContactInfo().setAccount(new ContactAccountInfo().setAccountValue(contact.getString(contact.getColumnIndexOrThrow(Phone.NUMBER))).setType(Common.Phone))
					.setName(new Name().setFirstName(contact.getString(contact.getColumnIndexOrThrow(Phone.DISPLAY_NAME)))));
			map.put(contact.getString(contact.getColumnIndexOrThrow(Phone.RAW_CONTACT_ID)), contact.getString(contact.getColumnIndexOrThrow(Phone.DISPLAY_NAME)));
			map_version.put(contact.getString(contact.getColumnIndexOrThrow(Phone.RAW_CONTACT_ID)), contact.getInt(contact.getColumnIndexOrThrow(Phone.DATA_VERSION)));
		}
		
		@Override
		public void onNameChanged(Cursor contact, Cursor app) {
			/**
			 * 변경된 이름 반영 - addcontact
			 */
			applicationcCPO.add(ContactDatabaseHelper.updateContact(app.getLong(app.getColumnIndexOrThrow(ContactTable.KEY_CONTACT_PHONE_ID)),
					ContactTable.KEY_CONTACT_NAME,
					contact.getString(contact.getColumnIndexOrThrow(Phone.DISPLAY_NAME)),
					contact.getString(contact.getColumnIndexOrThrow(Phone.DATA_VERSION))));
			
			mAddContactsReq.addContact(new ContactInfo().setAccount(new ContactAccountInfo().setAccountValue(contact.getString(contact.getColumnIndexOrThrow(Phone.NUMBER))).setType(Common.Phone))
					.setName(new Name().setFirstName(contact.getString(contact.getColumnIndexOrThrow(Phone.DISPLAY_NAME)))));
			map.put(contact.getString(contact.getColumnIndexOrThrow(Phone.RAW_CONTACT_ID)), contact.getString(contact.getColumnIndexOrThrow(Phone.DISPLAY_NAME)));
			map_version.put(contact.getString(contact.getColumnIndexOrThrow(Phone.RAW_CONTACT_ID)), contact.getInt(contact.getColumnIndexOrThrow(Phone.DATA_VERSION)));
		}
	};
	
	
	
	@Override
	protected TcpEnvelope onPreExecute() {
		ContactComparator.compareNumber(action);
		
		TcpEnvelope rev = new TcpEnvelope.Builder()
			.setType(TcpEnvelope.REQUEST)
			.setMessage(mAddContactsReq)
			.setMethodId(Session.Contact.AddContacts)
			.build();
		
		return rev;
	}

	@Override
	protected void onPostExecute(int resultCode, Object sentObject,	Object receivedObject) {
		MTalkLogWriter.d("AddContactsTask.onPostExecute() resultCode : " + resultCode);
		if (receivedObject == null) {
			mUiHandler.sendMessageAtFrontOfQueue(mUiHandler.obtainMessage(HandlerMsgConst.HANDLER_UNKNOWN_ERROR));
			return;
		}
		
		TcpEnvelope resultEnvelope = (TcpEnvelope) receivedObject;
		AddContactsRes addContactsRes = (AddContactsRes) resultEnvelope.getMessage();
		
		MTalkLogWriter.d("AddContactsTask ResponseCode : " + addContactsRes.getResponseCode());
		
		try {
			mContext.getContentResolver().applyBatch(MTalkConstant.AUTHORITY, applicationcCPO);
		} catch (RemoteException e) {
			e.printStackTrace();
		} catch (OperationApplicationException e) {
			e.printStackTrace();
		}
		
		if(addContactsRes.getResponseCode() == Common.SUCCESS){
			ContactDatabaseHelper.insert(mContext, mAddContactsReq, map, map_version);
//			ContactDatabaseHelper.insert(mContext, mAddContactsReq);
			mUiHandler.sendMessageAtFrontOfQueue(mUiHandler.obtainMessage(HandlerMsgConst.HANDLER_ADD_CONTACTS_SUCCESS));
		} else {
			mUiHandler.sendMessageAtFrontOfQueue(mUiHandler.obtainMessage(HandlerMsgConst.HANDLER_ADD_CONTACTS_FAIL));
		}
	}
}
